home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2004 #9 / Amiga Plus CD - 2004 - No. 09.iso / amigaplus / tools / amigaos4_only / mpega_libmad / library_init.c < prev    next >
C/C++ Source or Header  |  2004-08-03  |  29KB  |  1,062 lines

  1. #include "library_init.h"
  2.  
  3. #include <exec/memory.h>
  4. #include <exec/resident.h>
  5. #include <exec/initializers.h>
  6.  
  7. #include "wrap_mpega.h"
  8.  
  9. #ifdef BUILD_POWERUP
  10. #include <proto/ppc.h>
  11. #include "support_pup.h"
  12. #elif defined(BUILD_WARPUP)
  13. #include <powerpc/powerpc.h>
  14. #include <proto/powerpc.h>
  15. #include "support.h"
  16. #else
  17. #include "support.h"
  18. #endif
  19.  
  20. #ifdef BUILD_WARPUP
  21. #define CallPPCFunc(func, p1, p2, p3) \
  22. ({struct PPCArgs args; \
  23.     args.PP_Flags = PPF_LINEAR; \
  24.     args.PP_Stack = NULL; \
  25.     args.PP_StackSize = 0; \
  26.     args.PP_Code = (APTR)func; \
  27.     args.PP_Offset = 0; \
  28.     args.PP_Regs[0] = (ULONG)p1; \
  29.     args.PP_Regs[1] = (ULONG)p2; \
  30.     args.PP_Regs[2] = (ULONG)p3; \
  31.     RunPPC(&args); \
  32.     args.PP_Regs[0]; \
  33. })
  34.  
  35. struct MPEGABase
  36. {
  37.     struct Library lib;
  38. };
  39.  
  40. #pragma libbase MPEGABase
  41.  
  42. const char LibVersionString[] = "$VER: " LIB_ID;
  43. const char LibNameString[] = LIB_NAME;
  44.  
  45. void INIT_3_InitLibraries(__REGA6(struct Library *base))
  46. {
  47.     /* At least v15.0 is needed for PPF_LINEAR */
  48.     if (PowerPCBase->lib_Version >= 15) {
  49.         if (CallPPCFunc(InitSupport, 0, 0, 0))
  50.             return;
  51.     }
  52.     abortLibInit();
  53. }
  54.  
  55. void EXIT_3_InitLibraries(__REGA6(struct Library *base))
  56. {
  57.     if (PowerPCBase->lib_Version >= 15)
  58.         CallPPCFunc(RemoveSupport, 0, 0, 0);
  59. }
  60.  
  61. #else    /* BUILD_WARPUP */
  62.  
  63. /* Reserved library-function and dummy entrypoint */
  64. LONG LIB_Reserved(void)
  65. {
  66. #ifdef BUILD_OS4
  67.     return 30;
  68. #else
  69.     return 0;
  70. #endif
  71. }
  72.  
  73. struct ExecBase *SysBase;
  74. struct DosLibrary *DOSBase;
  75.  
  76. #ifdef BUILD_OS4
  77. struct UtilityBase    *UtilityBase;
  78. struct ExecIFace    *IExec;
  79. struct DOSIFace        *IDOS;
  80. struct UtilityIFace    *IUtility;
  81.  
  82.  
  83. ///
  84. ULONG Obtain(struct Interface *Self)
  85. {
  86.     return Self->Data.RefCount++;
  87. }
  88.  
  89. ULONG Release(struct Interface *Self)
  90. {
  91.     return Self->Data.RefCount--;
  92. }
  93. ///
  94. ///
  95.  
  96. STATIC CONST APTR manager_vectors[] = {
  97.     (void *)Obtain,
  98.     (void *)Release,
  99.     (void *)0,
  100.     (void *)0,
  101.     (void *)LIB_Open,
  102.     (void *)LIB_Close,
  103.     (void *)LIB_Expunge,
  104.     (void *)0,
  105.     (void *)-1
  106. };
  107.  
  108. static struct TagItem libmanagerTags[] =
  109. {
  110.     {MIT_Name,             (ULONG)"__library"},
  111.     {MIT_VectorTable,      (ULONG)manager_vectors},
  112.     {MIT_Version,          1},
  113.     {TAG_DONE,             0}
  114. };
  115.  
  116. static void *main_vectors[]=
  117. {
  118.   (void *)Obtain,
  119.   (void *)Release,
  120.   (void *)NULL,
  121.   (void *)NULL,
  122.   LIB_MPEGA_open,
  123.   LIB_MPEGA_close,
  124.   LIB_MPEGA_decode_frame,
  125.   LIB_MPEGA_seek,
  126.   LIB_MPEGA_time,
  127.   LIB_MPEGA_find_sync,
  128.   LIB_MPEGA_scale,
  129.   (void *)-1
  130. };
  131.  
  132. struct TagItem mainTags[] =
  133. {
  134.         {MIT_Name,                 (ULONG)"main"},
  135.         {MIT_VectorTable,        (ULONG)main_vectors},
  136.         {MIT_Version,       1},
  137.         {TAG_DONE,          0}
  138. };
  139.  
  140. // MLT_INTERFACES array
  141. static ULONG libInterfaces[] =
  142. {
  143.     (ULONG)libmanagerTags,
  144.     (ULONG)mainTags,
  145.     0
  146. };
  147.  
  148. extern ULONG VecTable68K[];
  149.  
  150. STATIC struct TagItem initTab[] = {
  151.     {CLT_DataSize,         (ULONG)(sizeof(struct PrivateBase))},
  152.     {CLT_Interfaces,       (ULONG)libInterfaces},
  153.     {CLT_InitFunc,         (ULONG)LibInit},
  154.     {CLT_Vector68K,           (ULONG)VecTable68K},
  155.     {TAG_DONE,             0}
  156. };
  157.  
  158. static const char LibVersion[] = "$VER: " LIB_ID;
  159.  
  160. struct Resident    ROMTag = {
  161.     RTC_MATCHWORD,
  162.     &ROMTag,
  163.     (&ROMTag)+1,
  164.     RTF_AUTOINIT|RTF_NATIVE,
  165.     LIB_VERSION,
  166.     NT_LIBRARY,
  167.     0,
  168.     LIB_NAME,
  169.     &LibVersion[6],
  170.     initTab
  171. };
  172.  
  173. #else    /* BUILD_OS4 */
  174.  
  175. ULONG LibVectors[] = {
  176. #ifdef __MORPHOS__
  177.     FUNCARRAY_32BIT_NATIVE,
  178. #endif
  179.     (ULONG) &LIB_Open,
  180.     (ULONG) &LIB_Close,
  181.     (ULONG) &LIB_Expunge,
  182.     (ULONG) &LIB_Reserved,
  183.  
  184.     (ULONG) &LIB_MPEGA_open,
  185.     (ULONG) &LIB_MPEGA_close,
  186.     (ULONG) &LIB_MPEGA_decode_frame,
  187.     (ULONG) &LIB_MPEGA_seek,
  188.     (ULONG) &LIB_MPEGA_time,
  189.     (ULONG) &LIB_MPEGA_find_sync,
  190.     (ULONG) &LIB_MPEGA_scale,
  191.     0xFFFFFFFF
  192. };
  193.  
  194. struct LibInitStruct
  195. {
  196.     ULONG    LibSize;
  197.     void    *FuncTable;
  198.     void    *DataTable;
  199.     void    (*InitFunc)(void);
  200. };
  201.  
  202. struct LibInitStruct LibInitStruct = {
  203.     sizeof(struct PrivateBase),
  204.     LibVectors,
  205.     NULL,
  206.     (void (*)(void)) &LibInit
  207. };
  208.  
  209. static const char LibVersion[] = "$VER: " LIB_ID;
  210.  
  211. static const struct Resident RomTag __attribute__((__aligned__(2))) = {
  212.     RTC_MATCHWORD,
  213.     &RomTag,
  214.     &RomTag + 1,
  215. #ifdef __MORPHOS__
  216.     RTF_PPC | RTF_AUTOINIT,
  217. #else
  218.     RTF_AUTOINIT,
  219. #endif
  220.     LIB_VERSION,
  221.     NT_LIBRARY,
  222.     0,
  223.     LIB_NAME,
  224.     &LibVersion[6],
  225.     &LibInitStruct
  226. };
  227.  
  228.  
  229. #ifdef __MORPHOS__
  230. ULONG __amigappc__ = 1;
  231. #endif
  232.  
  233. #endif    /* !BUILD_WARPUP */
  234.  
  235. static void LibCleanup(struct PrivateBase *PrivateBase)
  236. {
  237. #ifdef BUILD_POWERUP
  238.     RemoveSupport(PrivateBase);
  239. #else
  240.     RemoveSupport();
  241. #endif
  242.  
  243.     if (DOSBase)
  244.     {
  245. #ifdef BUILD_OS4
  246.         DropInterface((struct Interface *)IDOS);
  247.         IDOS = NULL;
  248.  
  249.         DropInterface((struct Interface *)IUtility);
  250.         IUtility = NULL;
  251.  
  252.         CloseLibrary((struct Library *)UtilityBase);
  253.         UtilityBase = NULL;
  254. #endif
  255.  
  256.         CloseLibrary((struct Library *)DOSBase);
  257.         PrivateBase->pv_DOSBase = DOSBase = NULL;
  258.     }
  259. }
  260.  
  261. BPTR LibExpunge(struct PrivateBase *PrivateBase)
  262. {
  263. #ifdef BUILD_POWERUP
  264.     if (PrivateBase->ParentBase)
  265.     {
  266.         struct PrivateBase *OldBase = PrivateBase;
  267.  
  268.         PrivateBase = PrivateBase->ParentBase;
  269.  
  270.         FreeMem((APTR)((ULONG)(OldBase) - (ULONG)(OldBase->pv_Lib.lib_NegSize)),
  271.                 OldBase->pv_Lib.lib_NegSize + OldBase->pv_Lib.lib_PosSize);
  272.     }
  273. #endif
  274.  
  275.     if ((PrivateBase->pv_Lib.lib_OpenCnt == 0))
  276.     {
  277.         BPTR seglist;
  278.  
  279.         seglist = PrivateBase->pv_SegList;
  280.         Remove(&PrivateBase->pv_Lib.lib_Node);
  281.         LibCleanup(PrivateBase);
  282.  
  283. #ifdef BUILD_OS4
  284.         DeleteLibrary((struct Library *)PrivateBase);
  285. #else
  286.         FreeMem((APTR)((ULONG)(PrivateBase) - (ULONG)(PrivateBase->pv_Lib.lib_NegSize)),
  287.                 PrivateBase->pv_Lib.lib_NegSize + PrivateBase->pv_Lib.lib_PosSize);
  288. #endif
  289.  
  290.         return seglist;
  291.     } else PrivateBase->pv_Lib.lib_Flags |= LIBF_DELEXP;
  292.  
  293.     return 0L;
  294. }
  295.  
  296. #ifdef __MORPHOS__
  297. struct Library *LibInit(struct PrivateBase *PrivateBase, BPTR SegList, struct ExecBase *sysbase)
  298. #elif defined(BUILD_OS4)
  299. struct Library * ASM LibInit(REG(d0, struct PrivateBase *PrivateBase), REG(a0, BPTR SegList), REG(a6, struct ExecIFace *pIExec))
  300. #else
  301. struct Library * ASM LibInit(REG(d0, struct PrivateBase *PrivateBase), REG(a0, BPTR SegList), REG(a6, struct ExecBase *sysbase))
  302. #endif
  303. {
  304. #ifdef BUILD_OS4
  305.     struct ExecBase    *sysbase = (struct ExecBase *) pIExec->Data.LibBase;
  306.     IExec = pIExec;
  307. #endif
  308.     SysBase = sysbase;
  309.  
  310.     if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 36)))
  311.     {
  312. #ifdef BUILD_POWERUP
  313.         if (InitSupport(PrivateBase))
  314. #elif BUILD_OS4
  315.         if((IDOS = (struct DOSIFace *) GetInterface((struct Library *) DOSBase, "main", 1L, NULL)) &&
  316.            (UtilityBase = OpenLibrary("utility.library", 0L)) &&
  317.            (IUtility = (struct UtilityIFace *) GetInterface((struct Library *) UtilityBase, "main", 1L, NULL)) &&
  318.            InitSupport())
  319. #else
  320.         if (InitSupport())
  321. #endif
  322.         {
  323.             PrivateBase->pv_Lib.lib_Revision     = LIB_REVISION;
  324.             PrivateBase->pv_SegList              = SegList;
  325.             PrivateBase->pv_SysBase              = SysBase;
  326.             PrivateBase->pv_DOSBase              = DOSBase;
  327. #ifdef BUILD_POWERUP
  328.             PrivateBase->ParentBase              = NULL;
  329. #endif
  330.  
  331.             return &PrivateBase->pv_Lib;
  332.         }
  333.     }
  334.  
  335.     LibCleanup(PrivateBase);
  336.     return NULL;
  337. }
  338.  
  339. #ifdef __MORPHOS__
  340. struct Library *LIB_Open(void)
  341. {
  342.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  343. #elif defined(BUILD_OS4)
  344. struct Library * ASM LIB_Open(struct Interface *Self)
  345. {
  346.     struct PrivateBase *PrivateBase = (struct PrivateBase *) Self->Data.LibBase;
  347. #else
  348. struct Library * ASM LIB_Open(REG(a6, struct PrivateBase *PrivateBase))
  349. {
  350. #endif
  351. #ifdef BUILD_POWERUP
  352.     if (PrivateBase->pv_Lib.lib_OpenCnt > 0)
  353.     {
  354.         struct PrivateBase *NewBase;
  355.         ULONG BaseSize = PrivateBase->pv_Lib.lib_NegSize + PrivateBase->pv_Lib.lib_PosSize;
  356.  
  357.         if ((NewBase = AllocMem(BaseSize, MEMF_PUBLIC)))
  358.         {
  359.             CopyMem((APTR)((ULONG)PrivateBase - (ULONG)PrivateBase->pv_Lib.lib_NegSize), NewBase, BaseSize);
  360.             NewBase = (APTR)((ULONG)NewBase + (ULONG)PrivateBase->pv_Lib.lib_NegSize);
  361.  
  362.             NewBase->ParentBase = PrivateBase;
  363.             NewBase->pv_CallPPCData = NULL;
  364.             NewBase->pv_CallPPCMsg = NULL;
  365.             NewBase->pv_StartupData = NULL;
  366.             NewBase->pv_StartupMsg = NULL;
  367.             NewBase->pv_ReplyPort = NULL;
  368.             NewBase->pv_PPCPort = NULL;
  369.             NewBase->pv_Task = NULL;
  370.  
  371.             if (!InitDispatch(NewBase, MSGTYPE_HELLO))
  372.             {
  373.                 LibExpunge(NewBase);
  374.                 return NULL;
  375.             }
  376.  
  377.             PrivateBase->pv_Lib.lib_Flags &= ~LIBF_DELEXP;
  378.             PrivateBase->pv_Lib.lib_OpenCnt++;
  379.         }
  380.  
  381.         return &NewBase->pv_Lib;
  382.     } else {
  383.         if (!InitDispatch(PrivateBase, MSGTYPE_HELLO))
  384.         {
  385.             LibExpunge(PrivateBase);
  386.             return NULL;
  387.         }
  388. #endif
  389.     PrivateBase->pv_Lib.lib_Flags &= ~LIBF_DELEXP;
  390.     PrivateBase->pv_Lib.lib_OpenCnt++;
  391.  
  392.     return &PrivateBase->pv_Lib;
  393. #ifdef BUILD_POWERUP
  394.     }
  395. #endif
  396. }
  397.  
  398. #ifdef __MORPHOS__
  399. BPTR LIB_Close(void)
  400. {
  401.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  402. #elif defined(BUILD_OS4)
  403. BPTR ASM LIB_Close(struct Interface *Self)
  404. {
  405.     struct PrivateBase *PrivateBase = (struct PrivateBase *) Self->Data.LibBase;
  406. #else
  407. BPTR ASM LIB_Close(REG(a6, struct PrivateBase *PrivateBase))
  408. {
  409. #endif
  410. #ifdef BUILD_POWERUP
  411.     RemoveDispatch(PrivateBase, MSGTYPE_GOODBYE);
  412.  
  413.     if (PrivateBase->ParentBase)
  414.     {
  415.         struct PrivateBase *OldBase = PrivateBase;
  416.  
  417.         PrivateBase = PrivateBase->ParentBase;
  418.  
  419.         FreeMem((APTR)((ULONG)(OldBase) - (ULONG)(OldBase->pv_Lib.lib_NegSize)),
  420.                 OldBase->pv_Lib.lib_NegSize + OldBase->pv_Lib.lib_PosSize);
  421.     }
  422. #endif
  423.  
  424.     if (PrivateBase->pv_Lib.lib_OpenCnt > 0) PrivateBase->pv_Lib.lib_OpenCnt--;
  425.  
  426.     if ((PrivateBase->pv_Lib.lib_OpenCnt == 0) && (PrivateBase->pv_Lib.lib_Flags & LIBF_DELEXP))
  427.         return LibExpunge(PrivateBase);
  428.  
  429.     return 0L;
  430. }
  431.  
  432. #ifdef __MORPHOS__
  433. BPTR LIB_Expunge(void)
  434. {
  435.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  436. #elif defined(BUILD_OS4)
  437. BPTR ASM LIB_Expunge(struct Interface *Self)
  438. {
  439.     struct PrivateBase *PrivateBase = (struct PrivateBase *) Self->Data.LibBase;
  440. #else
  441. BPTR ASM LIB_Expunge(REG(a6, struct PrivateBase *PrivateBase))
  442. {
  443. #endif
  444.  
  445.     return LibExpunge(PrivateBase);
  446. }
  447. #endif /* BUILD_WARPUP */
  448.  
  449. #ifdef __MORPHOS__
  450. MPEGA_STREAM *LIB_MPEGA_open(void)
  451. {
  452.     char *stream_name = (char *)REG_A0;
  453.     MPEGA_CTRL *ctrl = (MPEGA_CTRL *)REG_A1;
  454.     APTR a4base = (APTR)REG_A4;
  455.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  456.     struct Task *task = FindTask(NULL);
  457.     ULONG stacksize, stackused, stackreq = REQ_STACKSIZE;
  458.  
  459.     NewGetTaskAttrsA(task, &stacksize, sizeof(stacksize), TASKINFOTYPE_STACKSIZE, NULL);
  460.     NewGetTaskAttrsA(task, &stackused, sizeof(stackused), TASKINFOTYPE_USEDSTACKSIZE, NULL);
  461.  
  462.     if ((stacksize - stackused) < stackreq)
  463.     {
  464.         char *newstack;
  465.  
  466.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return NULL;
  467.  
  468.         PrivateBase->stackswap.stack.stk_Lower = newstack;
  469.         PrivateBase->stackswap.stack.stk_Upper = (ULONG)newstack + stackreq;
  470.  
  471.         PrivateBase->stackswap.Args[0] = (ULONG)stream_name;
  472.         PrivateBase->stackswap.Args[1] = (ULONG)ctrl;
  473.         PrivateBase->stackswap.Args[2] = (ULONG)a4base;
  474.  
  475.         PrivateBase->stackswap.Return = NewPPCStackSwap(&PrivateBase->stackswap.stack, WRAP_MPEGA_open, &PrivateBase->stackswap.Args);
  476.         FreeVec(newstack);
  477.     } else {
  478.         PrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_open(stream_name, ctrl, a4base);
  479.     }
  480.  
  481.     return (MPEGA_STREAM *)PrivateBase->stackswap.Return;
  482. }
  483. #else
  484. MPEGA_STREAM * LIB LIB_MPEGA_open(REG(a6, __IFACE_OR_BASE), REG(a0, char *stream_name), REG(a1, MPEGA_CTRL *ctrl), REG(a4, APTR a4base))
  485. {
  486. #ifdef BUILD_POWERUP
  487.     struct CallPPCData *CallPPCData;
  488.     APTR ReplyPort;
  489.     APTR CallPPCMsg;
  490.     ULONG Return;
  491.     APTR ThisTask = FindTask(NULL);
  492.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  493.  
  494.     /* Workaround for bad tasks that pass around the library base */
  495.     if (SigTask != ThisTask)
  496.     {
  497.         struct TagItem tmpTagList[1];
  498.  
  499.         tmpTagList[0].ti_Tag = TAG_DONE;
  500.         ReplyPort = PPCCreatePort(tmpTagList);
  501.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  502.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  503.     } else {
  504.         CallPPCData = PrivateBase->pv_CallPPCData;
  505.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  506.         ReplyPort = PrivateBase->pv_ReplyPort;
  507.     }
  508.  
  509.     CallPPCData->Type = MSGTYPE_CALL;
  510.     CallPPCData->PPCLVO = PPCLVO_MPEGA_open;
  511.     CallPPCData->Args[0] = (ULONG)stream_name;
  512.     CallPPCData->Args[1] = (ULONG)ctrl;
  513.     CallPPCData->Args[2] = (ULONG)a4base;
  514.  
  515.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  516.  
  517.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  518.  
  519.     PPCWaitPort(ReplyPort);
  520.     PPCGetMessage(ReplyPort);
  521.     Return = CallPPCData->Return;
  522.  
  523.     if (SigTask != ThisTask)
  524.     {
  525.         PPCDeleteMessage(CallPPCMsg);
  526.         PPCDeletePort(ReplyPort);
  527.         PPCFreeVec(CallPPCData);
  528.     }
  529.  
  530.     return (MPEGA_STREAM *)Return;
  531. #elif defined(BUILD_WARPUP)
  532.     return (MPEGA_STREAM *)CallPPCFunc(WRAP_MPEGA_open, stream_name, ctrl, a4base);
  533. #elif defined(BUILD_OS4)
  534.     return WRAP_MPEGA_open(stream_name, ctrl, a4base);
  535. #else
  536.     register struct PrivateBase *MyPrivateBase __asm("a3") = PrivateBase;
  537.     register char *stackptr __asm("sp");
  538.     struct Task *task;
  539.     long stackleft, stackreq = REQ_STACKSIZE;
  540.  
  541.     __asm("":"=r"(stackptr));    /* force gcc to acknowledge usage of the sp register */
  542.  
  543.     MyPrivateBase->stackswap.Args[0] = (ULONG)stream_name;
  544.     MyPrivateBase->stackswap.Args[1] = (ULONG)ctrl;
  545.     MyPrivateBase->stackswap.Args[2] = (ULONG)a4base;
  546.  
  547.     task = FindTask(NULL);
  548.     stackleft = stackptr - (char *)task->tc_SPLower;
  549.  
  550.     if (stackleft < stackreq)
  551.     {
  552.         char *newstack;
  553.  
  554.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return NULL;
  555.  
  556.         MyPrivateBase->stackswap.stack.stk_Lower = newstack;
  557.         MyPrivateBase->stackswap.stack.stk_Pointer = newstack + stackreq;
  558.         MyPrivateBase->stackswap.stack.stk_Upper = (ULONG)MyPrivateBase->stackswap.stack.stk_Pointer;
  559.  
  560.         StackSwap(&MyPrivateBase->stackswap.stack);
  561.  
  562.         MyPrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_open((char *)MyPrivateBase->stackswap.Args[0], (MPEGA_CTRL *)MyPrivateBase->stackswap.Args[1], (APTR)MyPrivateBase->stackswap.Args[2]);
  563.  
  564.         StackSwap(&MyPrivateBase->stackswap.stack);
  565.  
  566.         FreeVec(newstack);
  567.         return (MPEGA_STREAM *)MyPrivateBase->stackswap.Return;
  568.     } else {
  569.         return WRAP_MPEGA_open((char *)MyPrivateBase->stackswap.Args[0], (MPEGA_CTRL *)MyPrivateBase->stackswap.Args[1], (APTR)MyPrivateBase->stackswap.Args[2]);
  570.     }
  571. #endif
  572. }
  573. #endif
  574.  
  575. #ifdef __MORPHOS__
  576. void LIB_MPEGA_close(void)
  577. {
  578.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  579.     APTR a4base = (APTR)REG_A4;
  580. #else
  581. void LIB LIB_MPEGA_close(REG(a6, __IFACE_OR_BASE), REG(a0, MPEGA_STREAM *mpega_stream), REG(a4, APTR a4base))
  582. {
  583. #endif
  584. #ifdef BUILD_POWERUP
  585.     struct CallPPCData *CallPPCData;
  586.     APTR ReplyPort;
  587.     APTR CallPPCMsg;
  588.     APTR ThisTask = FindTask(NULL);
  589.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  590.  
  591.     /* Workaround for bad tasks that pass around the library base */
  592.     if (SigTask != ThisTask)
  593.     {
  594.         struct TagItem tmpTagList[1];
  595.  
  596.         tmpTagList[0].ti_Tag = TAG_DONE;
  597.         ReplyPort = PPCCreatePort(tmpTagList);
  598.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  599.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  600.     } else {
  601.         CallPPCData = PrivateBase->pv_CallPPCData;
  602.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  603.         ReplyPort = PrivateBase->pv_ReplyPort;
  604.     }
  605.  
  606.     CallPPCData->Type = MSGTYPE_CALL;
  607.     CallPPCData->PPCLVO = PPCLVO_MPEGA_close;
  608.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  609.     CallPPCData->Args[1] = (ULONG)a4base;
  610.  
  611.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  612.  
  613.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  614.  
  615.     PPCWaitPort(ReplyPort);
  616.     PPCGetMessage(ReplyPort);
  617.  
  618.     if (SigTask != ThisTask)
  619.     {
  620.         PPCDeleteMessage(CallPPCMsg);
  621.         PPCDeletePort(ReplyPort);
  622.         PPCFreeVec(CallPPCData);
  623.     }
  624. #elif defined(BUILD_WARPUP)
  625.     CallPPCFunc(WRAP_MPEGA_close, mpega_stream, a4base, 0);
  626. #else
  627.     WRAP_MPEGA_close(mpega_stream, a4base);
  628. #endif
  629. }
  630.  
  631. #ifdef __MORPHOS__
  632. LONG LIB_MPEGA_decode_frame(void)
  633. {
  634.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  635.     WORD **pcm = (WORD **)REG_A1;
  636.     APTR a4base = (APTR)a4base;
  637.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  638.     struct Task *task = FindTask(NULL);
  639.     ULONG stacksize, stackused, stackreq = REQ_STACKSIZE;
  640.  
  641.     NewGetTaskAttrsA(task, &stacksize, sizeof(stacksize), TASKINFOTYPE_STACKSIZE, NULL);
  642.     NewGetTaskAttrsA(task, &stackused, sizeof(stackused), TASKINFOTYPE_USEDSTACKSIZE, NULL);
  643.  
  644.     if ((stacksize - stackused) < stackreq)
  645.     {
  646.         char *newstack;
  647.  
  648.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  649.  
  650.         PrivateBase->stackswap.stack.stk_Lower = newstack;
  651.         PrivateBase->stackswap.stack.stk_Upper = (ULONG)newstack + stackreq;
  652.  
  653.         PrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  654.         PrivateBase->stackswap.Args[1] = (ULONG)pcm;
  655.         PrivateBase->stackswap.Args[2] = (ULONG)a4base;
  656.  
  657.         PrivateBase->stackswap.Return = NewPPCStackSwap(&PrivateBase->stackswap.stack, WRAP_MPEGA_decode_frame, &PrivateBase->stackswap.Args);
  658.         FreeVec(newstack);
  659.     } else {
  660.         PrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_decode_frame(mpega_stream, pcm, a4base);
  661.     }
  662.  
  663.     return (LONG)PrivateBase->stackswap.Return;
  664. }
  665. #else
  666. LONG LIB LIB_MPEGA_decode_frame(REG(a6, __IFACE_OR_BASE), REG(a0, MPEGA_STREAM *mpega_stream), REG(a1, WORD *pcm[MPEGA_MAX_CHANNELS]), REG(a4, APTR a4base))
  667. {
  668. #ifdef BUILD_POWERUP
  669.     struct CallPPCData *CallPPCData;
  670.     APTR ReplyPort;
  671.     APTR CallPPCMsg;
  672.     ULONG Return;
  673.     APTR ThisTask = FindTask(NULL);
  674.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  675.  
  676.     /* Workaround for bad tasks that pass around the library base */
  677.     if (SigTask != ThisTask)
  678.     {
  679.         struct TagItem tmpTagList[1];
  680.  
  681.         tmpTagList[0].ti_Tag = TAG_DONE;
  682.         ReplyPort = PPCCreatePort(tmpTagList);
  683.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  684.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  685.     } else {
  686.         CallPPCData = PrivateBase->pv_CallPPCData;
  687.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  688.         ReplyPort = PrivateBase->pv_ReplyPort;
  689.     }
  690.  
  691.     CallPPCData->Type = MSGTYPE_CALL;
  692.     CallPPCData->PPCLVO = PPCLVO_MPEGA_decode_frame;
  693.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  694.     CallPPCData->Args[1] = (ULONG)pcm;
  695.     CallPPCData->Args[2] = (ULONG)a4base;
  696.  
  697.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  698.  
  699.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  700.  
  701.     PPCWaitPort(ReplyPort);
  702.     PPCGetMessage(ReplyPort);
  703.     Return = CallPPCData->Return;
  704.  
  705.     if (SigTask != ThisTask)
  706.     {
  707.         PPCDeleteMessage(CallPPCMsg);
  708.         PPCDeletePort(ReplyPort);
  709.         PPCFreeVec(CallPPCData);
  710.     }
  711.  
  712.     return (LONG)Return;
  713. #elif defined(BUILD_WARPUP)
  714.     return (LONG)CallPPCFunc(WRAP_MPEGA_decode_frame, mpega_stream, pcm, a4base);
  715. #elif defined(BUILD_OS4)
  716.     return WRAP_MPEGA_decode_frame(mpega_stream, pcm, a4base);
  717. #else
  718.     register struct PrivateBase *MyPrivateBase __asm("a3") = PrivateBase;
  719.     register char *stackptr __asm("sp");
  720.     struct Task *task;
  721.     long stackleft, stackreq = REQ_STACKSIZE;
  722.  
  723.     __asm("":"=r"(stackptr));    /* force gcc to acknowledge usage of the sp register */
  724.  
  725.     MyPrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  726.     MyPrivateBase->stackswap.Args[1] = (ULONG)pcm;
  727.     MyPrivateBase->stackswap.Args[2] = (ULONG)a4base;
  728.  
  729.     task = FindTask(NULL);
  730.     stackleft = stackptr - (char *)task->tc_SPLower;
  731.  
  732.     if (stackleft < stackreq)
  733.     {
  734.         char *newstack;
  735.  
  736.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  737.  
  738.         MyPrivateBase->stackswap.stack.stk_Lower = newstack;
  739.         MyPrivateBase->stackswap.stack.stk_Pointer = newstack + stackreq;
  740.         MyPrivateBase->stackswap.stack.stk_Upper = (ULONG)MyPrivateBase->stackswap.stack.stk_Pointer;
  741.  
  742.         StackSwap(&MyPrivateBase->stackswap.stack);
  743.  
  744.         MyPrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_decode_frame((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (WORD **)MyPrivateBase->stackswap.Args[1], (APTR)MyPrivateBase->stackswap.Args[2]);
  745.  
  746.         StackSwap(&MyPrivateBase->stackswap.stack);
  747.  
  748.         FreeVec(newstack);
  749.         return (LONG)MyPrivateBase->stackswap.Return;
  750.     } else {
  751.         return WRAP_MPEGA_decode_frame((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (WORD **)MyPrivateBase->stackswap.Args[1], (APTR)MyPrivateBase->stackswap.Args[2]);
  752.     }
  753. #endif
  754. }
  755. #endif
  756.  
  757. #ifdef __MORPHOS__
  758. LONG LIB_MPEGA_seek(void)
  759. {
  760.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  761.     ULONG ms_time_position = (ULONG)REG_D0;
  762.     APTR a4base = (APTR)REG_A4;
  763.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  764.     struct Task *task = FindTask(NULL);
  765.     ULONG stacksize, stackused, stackreq = REQ_STACKSIZE;
  766.  
  767.     NewGetTaskAttrsA(task, &stacksize, sizeof(stacksize), TASKINFOTYPE_STACKSIZE, NULL);
  768.     NewGetTaskAttrsA(task, &stackused, sizeof(stackused), TASKINFOTYPE_USEDSTACKSIZE, NULL);
  769.  
  770.     if ((stacksize - stackused) < stackreq)
  771.     {
  772.         char *newstack;
  773.  
  774.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  775.  
  776.         PrivateBase->stackswap.stack.stk_Lower = newstack;
  777.         PrivateBase->stackswap.stack.stk_Upper = (ULONG)newstack + stackreq;
  778.  
  779.         PrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  780.         PrivateBase->stackswap.Args[1] = (ULONG)ms_time_position;
  781.         PrivateBase->stackswap.Args[2] = (ULONG)a4base;
  782.  
  783.         PrivateBase->stackswap.Return = NewPPCStackSwap(&PrivateBase->stackswap.stack, WRAP_MPEGA_seek, &PrivateBase->stackswap.Args);
  784.         FreeVec(newstack);
  785.     } else {
  786.         PrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_seek(mpega_stream, ms_time_position, a4base);
  787.     }
  788.  
  789.     return (LONG)PrivateBase->stackswap.Return;
  790. }
  791. #else
  792. LONG LIB LIB_MPEGA_seek(REG(a6, __IFACE_OR_BASE), REG(a0, MPEGA_STREAM *mpega_stream), REG(d0, ULONG ms_time_position), REG(a4, APTR a4base))
  793. {
  794. #ifdef BUILD_POWERUP
  795.     struct CallPPCData *CallPPCData;
  796.     APTR ReplyPort;
  797.     APTR CallPPCMsg;
  798.     ULONG Return;
  799.     APTR ThisTask = FindTask(NULL);
  800.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  801.  
  802.     /* Workaround for bad tasks that pass around the library base */
  803.     if (SigTask != ThisTask)
  804.     {
  805.         struct TagItem tmpTagList[1];
  806.  
  807.         tmpTagList[0].ti_Tag = TAG_DONE;
  808.         ReplyPort = PPCCreatePort(tmpTagList);
  809.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  810.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  811.     } else {
  812.         CallPPCData = PrivateBase->pv_CallPPCData;
  813.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  814.         ReplyPort = PrivateBase->pv_ReplyPort;
  815.     }
  816.  
  817.     CallPPCData->Type = MSGTYPE_CALL;
  818.     CallPPCData->PPCLVO = PPCLVO_MPEGA_seek;
  819.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  820.     CallPPCData->Args[1] = (ULONG)ms_time_position;
  821.     CallPPCData->Args[2] = (ULONG)a4base;
  822.  
  823.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  824.  
  825.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  826.  
  827.     PPCWaitPort(ReplyPort);
  828.     PPCGetMessage(ReplyPort);
  829.     Return = CallPPCData->Return;
  830.  
  831.     if (SigTask != ThisTask)
  832.     {
  833.         PPCDeleteMessage(CallPPCMsg);
  834.         PPCDeletePort(ReplyPort);
  835.         PPCFreeVec(CallPPCData);
  836.     }
  837.  
  838.     return (LONG)Return;
  839. #elif defined(BUILD_WARPUP)
  840.     return (LONG)CallPPCFunc(WRAP_MPEGA_seek, mpega_stream, ms_time_position, a4base);
  841. #elif defined(BUILD_OS4)
  842.     return WRAP_MPEGA_seek(mpega_stream, ms_time_position, a4base);
  843. #else
  844.     register struct PrivateBase *MyPrivateBase __asm("a3") = PrivateBase;
  845.     register char *stackptr __asm("sp");
  846.     struct Task *task;
  847.     long stackleft, stackreq = REQ_STACKSIZE;
  848.  
  849.     __asm("":"=r"(stackptr));    /* force gcc to acknowledge usage of the sp register */
  850.  
  851.     MyPrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  852.     MyPrivateBase->stackswap.Args[1] = (ULONG)ms_time_position;
  853.     MyPrivateBase->stackswap.Args[2] = (ULONG)a4base;
  854.  
  855.     task = FindTask(NULL);
  856.     stackleft = stackptr - (char *)task->tc_SPLower;
  857.  
  858.     if (stackleft < stackreq)
  859.     {
  860.         char *newstack;
  861.  
  862.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  863.  
  864.         MyPrivateBase->stackswap.stack.stk_Lower = newstack;
  865.         MyPrivateBase->stackswap.stack.stk_Pointer = newstack + stackreq;
  866.         MyPrivateBase->stackswap.stack.stk_Upper = (ULONG)MyPrivateBase->stackswap.stack.stk_Pointer;
  867.  
  868.         StackSwap(&MyPrivateBase->stackswap.stack);
  869.  
  870.         MyPrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_seek((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (ULONG)MyPrivateBase->stackswap.Args[1], (APTR)MyPrivateBase->stackswap.Args[2]);
  871.  
  872.         StackSwap(&MyPrivateBase->stackswap.stack);
  873.  
  874.         FreeVec(newstack);
  875.         return (LONG)MyPrivateBase->stackswap.Return;
  876.     } else {
  877.         return WRAP_MPEGA_seek((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (ULONG)MyPrivateBase->stackswap.Args[1], (APTR)MyPrivateBase->stackswap.Args[2]);
  878.     }
  879. #endif
  880. }
  881. #endif
  882.  
  883. #ifdef __MORPHOS__
  884. LONG LIB_MPEGA_time(void)
  885. {
  886.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  887.     ULONG *ms_time_position = (ULONG *)REG_A1;
  888. #else
  889. LONG LIB LIB_MPEGA_time(REG(a6, __IFACE_OR_BASE), REG(a0, MPEGA_STREAM *mpega_stream), REG(a1, ULONG *ms_time_position))
  890. {
  891. #endif
  892. #ifdef BUILD_POWERUP
  893.     struct CallPPCData *CallPPCData;
  894.     APTR ReplyPort;
  895.     APTR CallPPCMsg;
  896.     ULONG Return;
  897.     APTR ThisTask = FindTask(NULL);
  898.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  899.  
  900.     /* Workaround for bad tasks that pass around the library base */
  901.     if (SigTask != ThisTask)
  902.     {
  903.         struct TagItem tmpTagList[1];
  904.  
  905.         tmpTagList[0].ti_Tag = TAG_DONE;
  906.         ReplyPort = PPCCreatePort(tmpTagList);
  907.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  908.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  909.     } else {
  910.         CallPPCData = PrivateBase->pv_CallPPCData;
  911.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  912.         ReplyPort = PrivateBase->pv_ReplyPort;
  913.     }
  914.  
  915.     CallPPCData->Type = MSGTYPE_CALL;
  916.     CallPPCData->PPCLVO = PPCLVO_MPEGA_time;
  917.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  918.     CallPPCData->Args[1] = (ULONG)ms_time_position;
  919.  
  920.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  921.  
  922.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  923.  
  924.     PPCWaitPort(ReplyPort);
  925.     PPCGetMessage(ReplyPort);
  926.     Return = CallPPCData->Return;
  927.  
  928.     if (SigTask != ThisTask)
  929.     {
  930.         PPCDeleteMessage(CallPPCMsg);
  931.         PPCDeletePort(ReplyPort);
  932.         PPCFreeVec(CallPPCData);
  933.     }
  934.  
  935.     return (LONG)Return;
  936. #elif defined(BUILD_WARPUP)
  937.     return (LONG)CallPPCFunc(WRAP_MPEGA_time, mpega_stream, ms_time_position, 0);
  938. #else
  939.     return WRAP_MPEGA_time(mpega_stream, ms_time_position);
  940. #endif
  941. }
  942.  
  943. #ifdef __MORPHOS__
  944. LONG LIB_MPEGA_find_sync(void)
  945. {
  946.     UBYTE *buffer = (UBYTE *)REG_A0;
  947.     LONG buffer_size = (LONG)REG_D0;
  948. #else
  949. LONG LIB LIB_MPEGA_find_sync(REG(a6, __IFACE_OR_BASE), REG(a0, UBYTE *buffer), REG(d0, LONG buffer_size))
  950. {
  951. #endif
  952. #ifdef BUILD_POWERUP
  953.     struct CallPPCData *CallPPCData;
  954.     APTR ReplyPort;
  955.     APTR CallPPCMsg;
  956.     ULONG Return;
  957.     APTR ThisTask = FindTask(NULL);
  958.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  959.  
  960.     /* Workaround for bad tasks that pass around the library base */
  961.     if (SigTask != ThisTask)
  962.     {
  963.         struct TagItem tmpTagList[1];
  964.  
  965.         tmpTagList[0].ti_Tag = TAG_DONE;
  966.         ReplyPort = PPCCreatePort(tmpTagList);
  967.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  968.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  969.     } else {
  970.         CallPPCData = PrivateBase->pv_CallPPCData;
  971.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  972.         ReplyPort = PrivateBase->pv_ReplyPort;
  973.     }
  974.  
  975.     CallPPCData->Type = MSGTYPE_CALL;
  976.     CallPPCData->PPCLVO = PPCLVO_MPEGA_find_sync;
  977.     CallPPCData->Args[0] = (ULONG)buffer;
  978.     CallPPCData->Args[1] = (ULONG)buffer_size;
  979.  
  980.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  981.  
  982.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  983.  
  984.     PPCWaitPort(ReplyPort);
  985.     PPCGetMessage(ReplyPort);
  986.     Return = CallPPCData->Return;
  987.  
  988.     if (SigTask != ThisTask)
  989.     {
  990.         PPCDeleteMessage(CallPPCMsg);
  991.         PPCDeletePort(ReplyPort);
  992.         PPCFreeVec(CallPPCData);
  993.     }
  994.  
  995.     return (LONG)Return;
  996. #elif defined(BUILD_WARPUP)
  997.     return (LONG)CallPPCFunc(WRAP_MPEGA_find_sync, buffer, buffer_size, 0);
  998. #else
  999.     return WRAP_MPEGA_find_sync(buffer, buffer_size);
  1000. #endif
  1001. }
  1002.  
  1003. #ifdef __MORPHOS__
  1004. LONG LIB_MPEGA_scale(void)
  1005. {
  1006.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  1007.     LONG scale_percent = (LONG)REG_D0;
  1008. #else
  1009. LONG LIB LIB_MPEGA_scale(REG(a6, __IFACE_OR_BASE), REG(a0, MPEGA_STREAM *mpega_stream), REG(d0, LONG scale_percent))
  1010. {
  1011. #endif
  1012. #ifdef BUILD_POWERUP
  1013.     struct CallPPCData *CallPPCData;
  1014.     APTR ReplyPort;
  1015.     APTR CallPPCMsg;
  1016.     ULONG Return;
  1017.     APTR ThisTask = FindTask(NULL);
  1018.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  1019.  
  1020.     /* Workaround for bad tasks that pass around the library base */
  1021.     if (SigTask != ThisTask)
  1022.     {
  1023.         struct TagItem tmpTagList[1];
  1024.  
  1025.         tmpTagList[0].ti_Tag = TAG_DONE;
  1026.         ReplyPort = PPCCreatePort(tmpTagList);
  1027.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  1028.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  1029.     } else {
  1030.         CallPPCData = PrivateBase->pv_CallPPCData;
  1031.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  1032.         ReplyPort = PrivateBase->pv_ReplyPort;
  1033.     }
  1034.  
  1035.     CallPPCData->Type = MSGTYPE_CALL;
  1036.     CallPPCData->PPCLVO = PPCLVO_MPEGA_scale;
  1037.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  1038.     CallPPCData->Args[1] = (ULONG)scale_percent;
  1039.  
  1040.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  1041.  
  1042.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  1043.  
  1044.     PPCWaitPort(ReplyPort);
  1045.     PPCGetMessage(ReplyPort);
  1046.     Return = CallPPCData->Return;
  1047.  
  1048.     if (SigTask != ThisTask)
  1049.     {
  1050.         PPCDeleteMessage(CallPPCMsg);
  1051.         PPCDeletePort(ReplyPort);
  1052.         PPCFreeVec(CallPPCData);
  1053.     }
  1054.  
  1055.     return (LONG)Return;
  1056. #elif defined(BUILD_WARPUP)
  1057.     return (LONG)CallPPCFunc(WRAP_MPEGA_scale, mpega_stream, scale_percent, 0);
  1058. #else
  1059.     return WRAP_MPEGA_scale(mpega_stream, scale_percent);
  1060. #endif
  1061. }
  1062.